package walace.stocktracer;

import java.io.IOException;
//import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
//import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

import android.util.Log;

class StockItem
{
	public StockItem()
	{			
		reset();
		sym = "";
	}	
	public StockItem(String sym)
	{
		reset();
		this.sym = sym;
	}
	public void reset()
	{		
		name = "---";
		price = 0;
		change_percent = 0;
		change = 0;
	}
	public String sym;
	public String name;	
	public float price;
	public float change_percent;
	public float change;
	public String error_msg;
}

public class StockDatabase{
	
	private static final String TAG = "StockInfo";
	private String mStrStatus = "";
	
	public boolean Test()
	{
		Log.d(TAG," Test start !");
		
        String str_error_msg;
		List<String> stock_symbol = new ArrayList<String>();
		stock_symbol.add(new String("3041.TW"));
		stock_symbol.add(new String("2330.TW"));
		StockDatabase stock = new StockDatabase();

		String str_ret = stock.GetInfo(stock_symbol);					
		if(str_ret == null) {
			str_error_msg = stock.GetErrorMessage();
			Log.e(TAG,"GetInfo test failed:" + str_error_msg);
			return false;
		} else {
			Log.d(TAG,"GetInfo test ok:" + str_ret);
		}
		
		String[] str_list_ret = stock.GetInfoList(stock_symbol);		
		if(str_list_ret == null) {
			str_error_msg = stock.GetErrorMessage();
			Log.e(TAG,"GetInfoList test failed:" + str_error_msg);
			return false;
		}else {
			
			for(String ret:str_list_ret)
				Log.d(TAG, ret);
			Log.d(TAG,"GetInfoList test ok");
		}
		
		List<StockItem> items_list = new ArrayList<StockItem>();
		items_list.add(new StockItem("3041.TW"));
		items_list.add(new StockItem("2330.TW"));
		
		if(!stock.UpdateItems(items_list))
		{
			str_error_msg = stock.GetErrorMessage();
			Log.e(TAG, "GetInfoItems test failed:" + str_error_msg);
			return false;
		} else {
			for(StockItem item:items_list)
				Log.d(TAG, item.sym + "," + item.name + "," + item.price + "," + item.change_percent + "," + item.change);	
			Log.d(TAG, "GetInfoItems test ok");
		}
		
		Log.d(TAG, "Test done !!");	
		return true;		
	}
	
	/*
	 * http://blog4kevin.sinaapp.com/index.php/archives/256
	 * http://finance.yahoo.com/d/quotes.csv?s=3041.TW&f=snl1p2
	 * http://finance.yahoo.com/d/quotes.csv?s=3041.TW&f=snl1p2c6
	 */
	private static final String API_PARAMETERS = "&f=snl1p2c6";
	private static final int API_PARA_INDEX_SYM = 0;
	private static final int API_PARA_INDEX_NAME = 1;
	private static final int API_PARA_INDEX_LAST_TRADE = 2;
	private static final int API_PARA_INDEX_CHANGE_PERCENT = 3;
	private static final int API_PARA_INDEX_CHANGE = 4;
	
	public boolean UpdateItems(List<StockItem> items_list)
	{
		String para = "s=";	
		boolean skip_first_plus = true;
	    for(StockItem item:items_list)
	    {
	    	if(skip_first_plus)
	    	{
	    		skip_first_plus = false;
	    	}
	    	else
	    	{
	    	para+="+";
	    }	
	    
	    	para += item.sym;
	    	
	    }	
	    
		para += API_PARAMETERS;
		String ret_str = HttpGetQuery("http://finance.yahoo.com/d/quotes.csv?"+para);
		
		Log.d(TAG, "HttpGetQuery:" + ret_str);
		
		String[] str_items_array = null;
		
		if(ret_str == null || ret_str == "")
			return false;
		
		ret_str = ret_str.replaceAll("\"", "");
		ret_str = ret_str.replace("%", "");
		ret_str = ret_str.replace("\r", "");
		
		Log.d(TAG, "after replace: " + ret_str);

		str_items_array = ret_str.split("\n");

		if(str_items_array == null)
			return false;
		
		String[] str_members_array = null;
		for(String str:str_items_array)
		{
			str_members_array = str.split(",");
			if(str_members_array == null)
				return false;
			SetStockItem(items_list,str_members_array);
		}
		return true;
	}
	
	public String[] GetInfoList(List<String> stock_symbol)
	{
		//List<NameValuePair> pairs = new ArrayList<NameValuePair>();
		
		Iterator<String> iterator = stock_symbol.iterator();
		String para = "s=";
	    while(true)
	    {
	    	para += (String) iterator.next();
	    	if(!iterator.hasNext())
	    	{
	    		break;
	    	}
	    	para+="+";
	    }		    
	    para += API_PARAMETERS;	   
		//pairs.add(new BasicNameValuePair("s",para));
		//pairs.add(new BasicNameValuePair("f","l1p2"));		
		//HttpPostQuery("http://finance.yahoo.com/d/quotes.csv",pairs);
	    //http://finance.yahoo.com/d/quotes.csv?s=3041.TW&f=snl1p2
	    String retStr = HttpGetQuery("http://finance.yahoo.com/d/quotes.csv?"+para);
		
		String[] ret_str_array = null;		
		if(retStr != null && retStr != "")
		{
			ret_str_array = retStr.split("\n");
		}
		return ret_str_array;
	}
	
	public String GetInfo(List<String> stock_symbol)
	{
		//List<NameValuePair> pairs = new ArrayList<NameValuePair>();		
		Iterator<String> iterator = stock_symbol.iterator();
		String para = "s=";
	    while(true)
	    {
	    	para += (String) iterator.next();
	    	if(!iterator.hasNext())
	    	{
	    		break;
	    	}
	    	para+="+";
	    }		    
	    para += API_PARAMETERS;	   
		//pairs.add(new BasicNameValuePair("s",para));
		//pairs.add(new BasicNameValuePair("f","l1p2"));		
		//HttpPostQuery("http://finance.yahoo.com/d/quotes.csv",pairs);
	    String retStr = HttpGetQuery("http://finance.yahoo.com/d/quotes.csv?"+para);		
		return retStr;
	}
	
	public String GetErrorMessage()
	{
		return mStrStatus;
	}

	private void SetStockItem(List<StockItem> items,String[] item_info)
	{
		for(StockItem item:items)
		{		
			//Log.d(TAG,item.sym + " <> " + item_info[API_PARA_INDEX_SYM] + " <> " + item_info[API_PARA_INDEX_NAME]);
			if(item.sym.equals(item_info[API_PARA_INDEX_SYM]))
			{
				try
				{					
					Log.d(TAG,"Update:" + item.sym + " <--> " + item_info[API_PARA_INDEX_SYM] + " <--> " + item_info[API_PARA_INDEX_NAME]);
					item.error_msg = null;
					item.price = Float.parseFloat(item_info[API_PARA_INDEX_LAST_TRADE]);
				    item.name = item_info[API_PARA_INDEX_NAME];
				    item.change_percent = Float.parseFloat(item_info[API_PARA_INDEX_CHANGE_PERCENT]);
				    item.change = Float.parseFloat(item_info[API_PARA_INDEX_CHANGE]);				
				}
				catch (Exception e)
				{
					Log.e(TAG," exception occuring...");
					item.reset();
					item.error_msg = "error";
				}
			}
		}		
	}
	
	@SuppressWarnings("unused")
	private String HttpPostQuery(String hostURL, List<NameValuePair> pairs) {
	        // Declare a content string prepared for returning.
		    String ret_str = null;
		
	        // Have an HTTP client to connect to the web service.
	        HttpClient httpClient = new DefaultHttpClient();
	        // Have an HTTP response container. 
	        HttpResponse httpResponse = null;
	        
	        ret_str = "";
	        mStrStatus = "";
	        
	        // This try & catch is prepared for the IO exception in case.
	        try {
	            // Have a post method class with the query URL.
	            HttpPost httpQuery = new HttpPost(hostURL);
	            // Assign the list as the arguments of post being UTF_8 encoding.
	            httpQuery.setEntity(new UrlEncodedFormEntity(pairs, HTTP.UTF_8));
	            
	            // The HTTP client do the query and have the string type response.
	            httpResponse = httpClient.execute(httpQuery);
	            
	            // Read the HTTP response content as an encoded string.
	            ret_str += EntityUtils.toString(httpResponse.getEntity());
	        }
	        // Catch the HTTP exception.
	        catch(ClientProtocolException ex) {
	        	mStrStatus += "ClientProtocolException:" + ex.getMessage();
	        	ret_str = null;
	        }
	        // Catch the any IO exception.
	        catch(IOException ex) {
	        	mStrStatus += "IOException:" + ex.getMessage();
	        	ret_str = null;
	        }
	        // The HTTP connection must be closed any way.
	        finally {
	            httpClient.getConnectionManager().shutdown();
	        }
	        
	        // Check the HTTP connection is executed or not.
	        if (httpResponse != null) {
	        	mStrStatus += httpResponse.getStatusLine().getStatusCode();
	        }
	        
	        return ret_str;
	    }
		
	private String HttpGetQuery(String hostURL) {
		
		String ret_str = null;

        // Declare a content string prepared for returning.
        // Have an HTTP client to connect to the web service.
        HttpClient httpClient = new DefaultHttpClient();
        // Have an HTTP response container. 
        HttpResponse httpResponse = null;
        
        ret_str = "";
        mStrStatus = "";
        // This try & catch is prepared for the IO exception in case.
        try {
            // Have a post method class with the query URL.
            HttpGet httpQuery = new HttpGet(hostURL);
            // The HTTP client do the query and have the string type response.
            httpResponse = httpClient.execute(httpQuery);
            
            // Read the HTTP headers and into content.
            //for (Header header : httpResponse.getAllHeaders()) {
            //     content += "\n" + header.toString();
            //}
            // Read the HTTP response content as an encoded string.
            ret_str += EntityUtils.toString(httpResponse.getEntity());
        }
        // Catch the HTTP exception.
        catch(ClientProtocolException ex) {
        	mStrStatus += "ClientProtocolException:" + ex.getMessage(); 
        	ret_str = null;
        }
        // Catch the any IO exception.
        catch(IOException ex) {
        	mStrStatus += "IOException:" + ex.getMessage();
        	ret_str = null;
        }
        // The HTTP connection must be closed any way.
        finally    {
            httpClient.getConnectionManager().shutdown();
        }
        
        // Check the HTTP connection is executed or not.
        if (httpResponse != null) {
            // Put the status code with status key.
        	mStrStatus += httpResponse.getStatusLine().getStatusCode();
        }
        
        return ret_str;
    }

}
